package com.company.cloud.acct.modules.app.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.acct.modules.app.controller.req.*;
import com.company.cloud.acct.modules.app.mapper.AcctAppMapper;
import com.company.cloud.acct.modules.app.service.AcctCashService;
import com.company.cloud.acct.modules.base.entity.AccountBillInfo;
import com.company.cloud.acct.modules.base.entity.AccountCashInfo;
import com.company.cloud.acct.modules.base.service.AccountBillInfoService;
import com.company.cloud.acct.modules.cache.models.AcctBillModel;
import com.company.cloud.acct.modules.cache.models.AcctBillMonthStatModel;
import com.company.cloud.acct.modules.cache.models.AcctCashModel;
import com.company.cloud.acct.modules.cache.models.BankCardModel;
import com.company.cloud.acct.modules.cache.utils.AcctConvertUtils;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.auth.annotation.Login;
import com.company.cloud.common.bean.BaseResult;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.AuthContextUtils;
import com.company.cloud.common.utils.LocalDateTimeUtils;
import com.company.cloud.common.utils.StrSplitUtils;
//import com.taobao.txc.datasource.cobar.TxcDataSource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


@Log4j2
@Login
@RestController
@RequestMapping("/app/acct/bill")
@Api(tags = "App_Acct_账户账单信息")
public class AcctBillController {

    @Autowired
    private AccountBillInfoService accountBillInfoService;

    @Resource
    private AcctAppMapper acctAppMapper;

    private LocalDateTime getStartDate(String startDate) {
//        TxcDataSource

        LocalDateTime _startDate;
        if (StringUtils.isEmpty(startDate)) {
            _startDate = LocalDateTime.now().minusYears(1);
        } else {
            _startDate = LocalDateTimeUtils.parse_yyyyMMdd(startDate);
        }
        return _startDate;
    }

    private LocalDateTime getEndDate(String endDate) {
        LocalDateTime _endDate;
        if (StringUtils.isEmpty(endDate)) {
//            _endDate= LocalDateTimeUtils.parse_yyyyMMddHHmmss(StrUtil.format("{}-01 00:00:00",
//                    LocalDateTimeUtils.format_yyyyMM(LocalDateTime.now())));
            _endDate = LocalDateTime.now();
        } else {
            _endDate = LocalDateTimeUtils.parse_yyyyMMdd(endDate);
        }
        return _endDate;
    }

    @PostMapping("/billStatTypeMonth")
    @ApiOperation(value = "账单月统计", response = AcctBillMonthStatModel.class)
    public BaseResult billStatTypeMonth(@RequestBody AcctBillStatTypeMonthParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        LocalDateTime startDt = this.getStartDate(params.getStartDate());
        LocalDateTime endDt = this.getEndDate(params.getEndDate());

        List<AcctBillMonthStatModel> list = acctAppMapper.queryAcctBillStatMonth(new QueryWrapper<AcctBillMonthStatModel>()
                .eq("user_id", userInfo.getId())
                .in("type", params.getTypes())
                .ge("cdt", startDt)
                .lt("cdt", endDt)
                .groupBy("type", "DATE_FORMAT(cdt,'%Y-%m')")
        );
        return BaseResult.ok(list);
    }


    @PostMapping("/billStatMonth2Item")
    @ApiOperation(value = "账单月统计(含明细)", response = AcctBillMonthStatModel.class)
    public BaseResult billStatTypeMonth2Item(@RequestBody AcctBillStat2ItemTypeMonthParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        LocalDateTime startDt = this.getStartDate(params.getStartDate());
        LocalDateTime endDt = this.getEndDate(params.getEndDate());

        List<AccountBillInfo> list = accountBillInfoService.list(new QueryWrapper<AccountBillInfo>()
                .eq("user_id", userInfo.getId())
                .eq("type", params.getType())
                .ge("cdt", startDt)
                .lt("cdt", endDt)
                .orderByDesc("cdt")
        );

        if (CollectionUtils.isEmpty(list)) {
            return BaseResult.ok();
        }

        Map<String, AcctBillMonthStatModel> map = new HashMap<String, AcctBillMonthStatModel>();
        for (AccountBillInfo billInfo : list) {
            String month = LocalDateTimeUtils.format_yyyyMM(billInfo.getCdt());
            AcctBillMonthStatModel abmsm = map.get(month);
            if (abmsm == null) {
                abmsm = new AcctBillMonthStatModel();
                abmsm.setType(billInfo.getType());
                abmsm.setMonth(month);
                abmsm.setTotalFundOp(BigDecimal.ZERO);
                abmsm.setTotalFundTax(BigDecimal.ZERO);
                abmsm.setTotalFundReal(BigDecimal.ZERO);
                map.put(month, abmsm);
            }
            abmsm.setTotalFundOp(abmsm.getTotalFundOp().add(billInfo.getFundOp()));
            abmsm.setTotalFundTax(abmsm.getTotalFundTax().add(billInfo.getFundTax()));
            abmsm.setTotalFundReal(abmsm.getTotalFundReal().add(billInfo.getFundReal()));
            abmsm.addAcctBill(AcctConvertUtils.getAcctBillModel(billInfo));
        }
        List<AcctBillMonthStatModel> data = new ArrayList<AcctBillMonthStatModel>();
        map.forEach((k, v) -> {
            data.add(v);
        });
        return BaseResult.ok(data);
    }

    @PostMapping("/billQuery")
    @ApiOperation(value = "账单查询", response = AcctBillModel.class)
    public BaseResult billQuery(@RequestBody AcctBillQueryPage4Param params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        LocalDateTime startDt = this.getStartDate(params.getStartDate());
        LocalDateTime endDt = this.getEndDate(params.getEndDate());

        IPage<AccountBillInfo> page = accountBillInfoService.page(new Page<>(params.getPage(), params.getRows()), new QueryWrapper<AccountBillInfo>()
                .eq("user_id", userInfo.getId())
                .eq(StringUtils.hasText(params.getType()), "type", params.getType())
                .eq(StringUtils.hasText(params.getRelObjType()), "rel_obj_type", params.getRelObjType())
                .eq(StringUtils.hasText(params.getRelObjNo()), "rel_obj_no", params.getRelObjNo())
                .eq(StringUtils.hasText(params.getInOut()), "in_out", params.getInOut())
                .eq(StringUtils.hasText(params.getState()), "state", params.getState())
                .like(StringUtils.hasText(params.getTags()), "tags", params.getTags())
                .ge("cdt", startDt)
                .lt("cdt", endDt)
        );
        IPage<AcctBillModel> data = page.convert(new Function<AccountBillInfo, AcctBillModel>() {
            @Override
            public AcctBillModel apply(AccountBillInfo entity) {
                return AcctConvertUtils.getAcctBillModel(entity);
            }
        });
        return BaseResult.ok(data);
    }

    @GetMapping("/billGet")
    @ApiOperation(value = "账单详细信息", response = AcctBillModel.class)
    public BaseResult billGet(@RequestParam("id") Integer id) {
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        AccountBillInfo entity = accountBillInfoService.getById(id);
        if (null == entity || !entity.getUserId().equals(userInfo.getId())) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        return BaseResult.ok(AcctConvertUtils.getAcctBillModel(entity));
    }


}
